package com.liveinstars.im.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baidu.unbiz.easymapper.MapperFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.liveinstars.im.domain.dao.model.ChatGroup;
import com.liveinstars.im.domain.dao.model.ChatGroupMember;
import com.liveinstars.im.domain.dao.model.Todo;
import com.liveinstars.im.domain.manager.ChatGroupManager;
import com.liveinstars.im.domain.manager.ChatGroupMemberManager;
import com.liveinstars.im.entity.ChatGroupP1;
import com.liveinstars.im.entity.ChatMessage;
import com.liveinstars.im.entity.Msg;
import com.liveinstars.im.entity.User;
import com.liveinstars.im.util.StringUtils;
import com.liveinstars.api.im.vo.UserVO;
import com.liveinstars.im.api.IMUserService;
import com.liveinstars.im.core.SessionManager;
import com.liveinstars.im.core.service.FriendsService;
import com.liveinstars.im.core.service.MessageService;
import com.liveinstars.im.core.service.TodoService;
import com.liveinstars.im.corebean.ClientRequestMessage;
import com.liveinstars.im.corebean.MsgHelper;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 1、保持服务器间的心态 2、转发消息
 * 
 * @author ting
 *
 */
@Sharable
@Service
public class ClientRequesHandler extends
		SimpleChannelInboundHandler<ClientRequestMessage> {

	private final static Logger logger = LoggerFactory.getLogger(ClientRequesHandler.class);

	@Autowired
	private SessionManager sessionManager;

	@Autowired
	private TodoService todoService;

	@Autowired
	private IMUserService IMUserService;

	@Autowired
	private ChatGroupManager chatGroupManager;

	@Autowired
	private ChatGroupMemberManager chatGroupMemberManager;

	@Autowired
	private MessageService messageService;

	@Autowired
	private FriendsService friendsService;


	@Override
	protected void channelRead0(ChannelHandlerContext channelHandlerContext,
			ClientRequestMessage message) throws Exception {

		// 客户端认证
		String channelId = channelHandlerContext.channel().id().toString();
		if (sessionManager.clientAuth(channelId) != null) {
			// 处理特定的消息
			String sessionKey = message.getUserId() + message.getToken();
			logger.info("ClientRequestMessage message.getRequestType() {} sessionKey {}",message.getRequestType(), sessionKey);
			JSONObject jsonObject = new JSONObject();
			String p = message.getParameter();
			if(!StringUtils.isEmpty(p)){
				logger.info("ClientRequestMessage getParameter {}",p);
				jsonObject = JSON.parseObject(p);
			}
			switch (message.getRequestType()) {
			case ClientRequestMessage.FRIEND_LIST:
				Msg.Message msg = getFriendsList(message);
				sessionManager.sendMessage(msg, channelId);
				break;
			case ClientRequestMessage.CHAT_MESSAGE_LIST:
				if(jsonObject == null){
					return;
				}
				int fromMessageId = jsonObject.getIntValue("id");
				String deviceType = jsonObject.getString("device");

				List<ChatMessage> ms = messageService.getAllOfflineChatMessageByToId((long)message.getUserId(), (long)fromMessageId);
				//移动端拉取一次离线消息后，删除离线消息，防止redis过大，另外还有定时任务会清理长期没有拉取过的过大的离线消息
				if(!"web".equals(deviceType)){
					messageService.clearALLChatMessageByToId((long)message.getUserId());
				}
				Msg.Message cmg = MsgHelper.newChatMessageListMessage(ms);
				sessionManager.sendMessage(cmg, channelId);
				//同时需要发送所有的附件消息
				break;
			case ClientRequestMessage.CHAT_MESSAGE_LIST_HISTORY:
				break;
			case ClientRequestMessage.TODO_LIST:
				int id = jsonObject.getIntValue("id");
				if(id != 0) {
					List<Todo> td = todoService.listUnCompleteTodoByUserIdAndStartId((long)message.getUserId(), (long)id);
					Msg.Message tmg = MsgHelper.newTodoListMessage(td);
					sessionManager.sendMessage(tmg, channelId);
				}
				break;

			case ClientRequestMessage.CHAT_GROUP_LIST:
				try {
					List<ChatGroupP1> chatGroupP1List = Lists.newArrayList();
					List<ChatGroupMember> chatGroupMemberList =
							chatGroupMemberManager.listByUserIdAndGroupType((long)message.getUserId(), 0);
					if (CollectionUtils.isNotEmpty(chatGroupMemberList)) {
						List<Long> chatGroupIdList = Lists.newArrayList();
						HashMap<Long, ChatGroupMember> groupMemberMap = Maps.newHashMap();
						chatGroupMemberList.forEach(chatGroupMember -> {
							chatGroupIdList.add(chatGroupMember.getChatGroupId());
							groupMemberMap.put(chatGroupMember.getChatGroupId(), chatGroupMember);
						});
						List<ChatGroup> chatGroupList = chatGroupManager.listByIds(chatGroupIdList);
						Map<Long, Integer> chatGroupMemberCountMap = chatGroupMemberManager.mapMemberCountByChatGroupIdList(chatGroupIdList);
						if (CollectionUtils.isNotEmpty(chatGroupList)) {
							MapperFactory.getCopyByRefMapper().mapClass(ChatGroup.class, ChatGroupP1.class).register();
							chatGroupP1List = chatGroupList.stream().map(chatGroup -> MapperFactory.getCopyByRefMapper().map(chatGroup,
									ChatGroupP1.class)).collect(Collectors.toList());
							for (ChatGroupP1 chatGroup : chatGroupP1List) {
								chatGroup.setUserCount(chatGroupMemberCountMap.get(chatGroup.getId()));
								chatGroup.setShield(groupMemberMap.get(chatGroup.getId()).getShield());
								chatGroup.setNoDisturbing(groupMemberMap.get(chatGroup.getId()).getNoDisturbing());
							}

						}
					}
					Msg.Message tcg = MsgHelper.newChatGroupListMessage2(chatGroupP1List);
					sessionManager.sendMessage(tcg, channelId);
				} catch (Exception e) {
					logger.error("CHAT_GROUP_LIST userId:{} msg:{}", message.getUserId(), e.getMessage(), e);
				}

				break;
			case ClientRequestMessage.RELATE_USER_LIST:
				List<User> users = IMUserService.getRelateUser((long) message.getUserId());
				Msg.Message ul = MsgHelper.newUserListMessage(users);
				sessionManager.sendMessage(ul, channelId);
				break;
			default:
				break;
			}

		} else {
			Msg.Message rtMessage = MsgHelper.newResultMessage(
					Msg.MessageType.AUTH_ERROR, "用户认证失败，重新认证!");

			logger.info("用户认证失败,重新认证！");
			channelHandlerContext.channel().writeAndFlush(rtMessage);
		}

		ReferenceCountUtil.release(message);
	}

	private Msg.Message getFriendsList(ClientRequestMessage message) {
		// 获取用户的好友列表
		List<UserVO> userList = friendsService.listFriendsByUserIdAndType(message.getUserId(), 1);
		return MsgHelper.newFriendsListMessage(userList);

	}
}